#ifndef DSPNASM_LINKER_H
#define DSPNASM_LINKER_H

#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
#include "lit/elf/elf.h"
#include "lit/elf/common.h"
#include "lit/elf/segList.h"
#include "lit/elf/symLink.h"

class ElfFile;

struct Linker {
    std::vector<std::string> segNames;      //链接关心的段
    std::shared_ptr<ElfFile> exe;           //链接后的输出文件
    std::shared_ptr<ElfFile> startOwner;    //拥有全局符号START/_start的文件
    std::vector<std::shared_ptr<ElfFile>> elfs; //所有目标文件对象
    std::unordered_map<std::string, std::shared_ptr<SegList>> segLists;  //所有合并段表序列
    std::vector<std::shared_ptr<SymLink>> symLinks; //所有符号引用信息，符号解析前存储未定义的符号prov字段为NULL
    std::vector<std::shared_ptr<SymLink>> symDef;   //所有符号定义信息recv字段NULL时标示该符号没有被任何文件引用，否则指向本身（同prov）
    std::string shstrtab;   // 段名字符串表
    std::string strtab;     // 字符串表

    Linker(){
        segNames.emplace_back(".text");
        segNames.emplace_back(".data");
        segLists[".text"] = std::make_shared<SegList>();
        segLists[".data"] = std::make_shared<SegList>();
    };

    ~Linker() = default;

    void addElf(const char *elfFileName); //添加一个目标文件
    void collectInfo();                   //搜集段信息和符号关联信息
    void symValid();                      //符号关联验证，分析符号间的关联（定义和引用），全局符号位置，出现非法符号逻辑返回false
    void allocAddr();                     //分配地址空间[重新计算虚拟地址空间，磁盘空间连续分布不重新计算]，其他的段全部删除
    void symParser();                     //符号解析，原地计算定义和未定义的符号虚拟地址
    void relocate();                      //符号重定位，根据所有目标文件的重定位项修正符号地址
    void assemExe();                      //组装可执行文件
    void exportElf(const char *fileName);      //输出elf
};

#endif //DSPNASM_LINKER_H
